﻿/*****************************************************************************
 
 Use of Ext is under the Ext JS license, for more information, 
 please visit http://extjs.com/products/license.php page. 
  
 You should confirm that you have read, understood and accept ethical criteria listed. 
 If not, see <http://www.mvcnext.com/license/>.
  
 Version: 1.0.0.0
 Website: http://www.mvcnext.com/
 
 Copyright (c) Yoganand R. All rights reserved.
 For continued development and updates, visit http://yogsbreath.net
 
 ******************************************************************************/
using System;
using System.Collections.Generic;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Collections;
using System.Web.UI;
using System.Text;

namespace MVCnExt.Web.UI.Ext
{
    /// <summary>
    /// An individual column's config object defines the header string, the Record field
    /// the column draws its data from, an optional rendering function to provide customized
    /// data formatting, and the ability to apply a CSS class to all cells in a column
    /// through its id config option.
    /// </summary>
    public class ExtColumn : ExtConfig
    {
        private List<ExtComponent> _editor = new List<ExtComponent>();

        public override IList<ScriptDescriptor> GetScriptDescriptors()
        {
            IList<ScriptDescriptor> list = base.GetScriptDescriptors();

            if (list.Count == 0)
                list.Add(new ExtScriptControlDescriptor(" ", "ctl00"));

            ScriptControlDescriptorBase desc = (ScriptControlDescriptorBase)list[0];

            desc.Type = " ";

            String[] properties = new String[]{
                "css", "dataIndex", "isfixed", "header", "hidden", "hideable", "menuDisabled",
                "groupable", "resizable", "sortable", "tooltip", "width"
            };

            Type component = typeof(ExtColumn);

            foreach (String property in properties)
            {
                PropertyInfo i = component.GetProperty(property);

                if (i == null)
                    throw new InvalidOperationException(String.Format("Property not found, 'ExtColumn.{0}'", property));

                Object value = i.GetValue(this, null);

                if (value == null)
                {
                    continue;
                }

                if (!(value is String))
                    desc.AddPropertyBase(property, value);
                else
                    desc.AddPropertyBase(property, String.Format("'{0}'", value));
            }

            //add editor controls
            if (editor.Count != 0)
            {
                // build editor template
                StringBuilder tabList = new StringBuilder();

                for (int i = 0; i < editor.Count; i++)
                {
                    // add comma between items
                    if (i != 0)
                    {
                        tabList.Append(",");
#if DEBUG
                        tabList.AppendLine("\t\t\t");
#endif
                    }

                    // get the editor script
                    IList<ScriptDescriptor> descriptors = editor[i].GetScriptDescriptors();

                    // write the editor's config to the list
                    tabList.Append(((ExtScriptControlDescriptor)descriptors[0]).WriteScript(ScriptType.NewOnly));
                }

                desc.AddPropertyBase("editor", tabList);
            }

            if (renderer != null)
            {
                properties = new String[]{
               "capitalize", "date", "dateRenderer", "htmlEncode", "lowercase", "stripTags", 
                "substr", "trim", "undef", "uppercase", "usMoney"    
                };

                component = typeof(ExtFormatUtil);

                foreach (String property in properties)
                {
                    PropertyInfo i = component.GetProperty(property);

                    if (i == null)
                        throw new InvalidOperationException(String.Format("Property not found, 'ExtFormatUtil.{0}'", property));

                    Object value = i.GetValue(renderer, null);

                    if (value == null)
                    {
                        continue;
                    }

                    if (!(value is String))
                        desc.AddPropertyBase("renderer", String.Format("Ext.util.Format.{0}({1})", property, value));
                    else
                        desc.AddPropertyBase("renderer", String.Format("Ext.util.Format.{0}('{1}')", property, value));
                }
            }


            return list;
        }

        #region Public Properties

        /// <summary>
        /// (optional) The Field to use when editing values in this column if editing is supported by the grid.
        /// </summary>
        [Description("(optional) The Ext.form.Field to use when editing values in this column if editing is supported by the grid.")]
        [NotifyParentProperty(true)]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public virtual List<ExtComponent> editor
        {
            get
            {
                return _editor;
            }
        }

        /// <summary>
        /// Reusable data formatting functions
        /// </summary>                      
        [Description("Reusable data formatting functions")]
        [Localizable(true)]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public ExtFormatUtil renderer { get; set; }

        /// <summary>
        /// (optional) Set custom CSS for all table cells in the column (excluding headers). Defaults to undefined.
        /// </summary>
        [Description("(optional) Set custom CSS for all table cells in the column (excluding headers). Defaults to undefined.")]
        public String css { get; set; }

        /// <summary>
        /// (optional) The name of the field in the grid's Store's Record definition from which
        /// to draw the column's value. If not specified, the column's index is used as an index
        /// into the Record's data Array.
        /// </summary>
        [Description("(optional) The name of the field in the grid's Ext.data.Store's Ext.data.Record definition from which to draw the column's value. If not specified, the column's index is used as an index into the Record's data Array.")]
        public String dataIndex { get; set; }

        /// <summary>
        /// (optional) True if the column width cannot be changed. Defaults to false.
        /// </summary>
        [Description("(optional) True if the column width cannot be changed. Defaults to false.")]
        public Boolean? isfixed { get; set; }

        /// <summary>
        /// The header text to display in the Grid view.
        /// </summary>
        [DefaultValue("")]
        [Description("The header text to display in the Grid view.")]
        public String header { get; set; }

        /// <summary>
        /// (optional) True to hide the column. Defaults to false.
        /// </summary>
        [Description("(optional) True to hide the column. Defaults to false.")]
        public Boolean? hidden { get; set; }

        /// <summary>
        /// (optional) Specify as false to prevent the user from hiding this column. Defaults to true.
        /// </summary>
        [DefaultValue(true)]
        [Description("(optional) Specify as false to prevent the user from hiding this column. Defaults to true.")]
        public Boolean? hideable { get; set; }

        /// <summary>
        /// (optional) Defaults to the column's initial ordinal position. A name which identifies
        /// this column. The id is used to create a CSS class name which is applied to all table
        /// cells (including headers) in that column. The class name takes the form of
        /// 
        /// x-grid3-td-id
        ///
        ///
        /// Header cells will also recieve this class name, but will also have the class x-grid3-hd,
        /// so to target header cells, use CSS selectors such as:
        /// 
        /// .x-grid3-hd.x-grid3-td-id
        /// 
        /// The AutoExpandColumn grid config option references the column via this identifier.
        /// </summary>
        [Description("(optional) Defaults to the column's initial ordinal position. A name which identifies this column. The id is used to create a CSS class name which is applied to all table cells (including headers) in that column.")]
        //If the name of this property as ID then VS throws compiler error if same Column ID exists in another Component on the Page.
        public String columnID { get; set; }

        /// <summary>
        /// (optional) True to disable the column menu. Defaults to false.
        /// </summary>
        [Description("(optional) True to disable the column menu. Defaults to false.")]
        public Boolean? menuDisabled { get; set; }

        /// <summary>
        /// (optional) False to disable grouping by this column. Defaults to true.
        /// </summary>
        [DefaultValue(true)]
        [Description("(optional) False to disable grouping by this column. Defaults to true.")]
        public Boolean? groupable { get; set; }

        /// <summary>
        /// (optional) False to disable column resizing. Defaults to true.
        /// </summary>
        [DefaultValue(true)]
        [Description("(optional) False to disable column resizing. Defaults to true.")]
        public Boolean? resizable { get; set; }

        /// <summary>
        /// (optional) True if sorting is to be allowed on this column. Defaults to the value
        /// of the defaultSortable property. Whether local/remote sorting is used is 
        /// specified in Ext.data.Store.remoteSort.
        /// </summary>
        [Description("(optional) True if sorting is to be allowed on this column. Defaults to the value of the defaultSortable property. Whether local/remote sorting is used is specified in Ext.data.Store.remoteSort.")]
        public Boolean? sortable { get; set; }

        /// <summary>
        /// (optional) A text string to use as the column header's tooltip. If Quicktips are enabled,
        /// this value will be used as the text of the quick tip, otherwise it will be set as the
        /// header's HTML title attribute. Defaults to ''.
        /// </summary>
        [Description("(optional) A text string to use as the column header's tooltip. If Quicktips are enabled, this value will be used as the text of the quick tip, otherwise it will be set as the header's HTML title attribute. Defaults to ''.")]
        public String tooltip { get; set; }

        /// <summary>
        /// (optional) The initial width in pixels of the column. Using this instead of Ext.grid.GridPanel.autoSizeColumns
        /// is more efficient.
        /// </summary>
        [DefaultValue(100)]
        [Description("(optional) The initial width in pixels of the column. Using this instead of Ext.grid.Grid.autoSizeColumns is more efficient.")]
        public Unit? width { get; set; }

        #endregion
    }
}
